package com.gs.xbinfomytest.aspect;

import com.alibaba.fastjson.JSONObject;
import com.gs.xbinfomytest.log.LogRecord;
import com.gs.xbinfomytest.util.HttpContextUtils;
import com.gs.xbinfomytest.util.IpUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @Created : IntelliJ IDEA.
 * @ProjectName: xbinfomytest
 * @Package: com.gs.xbinfomytest.aspect
 * @Author: guoshuai
 * @CreateDate: 2019/8/23 9:17
 * @Description: java类的作用描述
 * @Vsersion: 1.0
 */
@Component
@Aspect
public class LogRecordAspect {
    private org.slf4j.Logger logger = LoggerFactory.getLogger(LogRecordAspect.class);

    /**
     * 定义切入点，在注解的位置切入代码
     */
    @Pointcut("@annotation(com.gs.xbinfomytest.log.LogRecord)")
    public void logPointCut() {

    }

    /**
     * @param joinPoint 用于输出记录日志信息
     */
    // @AfterReturning("logPointCut()")
    @Before("logPointCut()")
    public void saveSysLog(JoinPoint joinPoint) {
        logger.info("切面。。。。。");

        //获取用户ip地址
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        logger.info("获取的ip是：" + IpUtils.getIpAddr(request));
        String usernameInfo = (String) request.getSession().getAttribute("usernameInfo");
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();
        //获取操作
        LogRecord myLog = method.getAnnotation(LogRecord.class);
        if (myLog != null) {
            logger.info("操作的描述是：" + myLog.value());
        }
        //获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();
        //获取请求的方法名
        String methodName = method.getName();
        logger.info("操作的方法是：" + methodName);
        //请求的参数
        Object[] args = joinPoint.getArgs();
        //将参数所在的数组转换成json
        if (args != null) {
            Object[] arguments = new Object[args.length];
            for (int i = 0; i < args.length; i++) {
                if (args[i] instanceof ServletRequest || args[i] instanceof ServletResponse || args[i] instanceof MultipartFile) {
                    //ServletRequest不能序列化，从入参里排除，否则报异常：java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
                    //ServletResponse不能序列化 从入参里排除，否则报异常：java.lang.IllegalStateException: getOutputStream() has already been called for this response
                    continue;
                }
                arguments[i] = args[i];
            }
            String paramter = "";
            if (arguments != null) {
                try {
                    paramter = JSONObject.toJSONString(arguments);
                } catch (Exception e) {
                    paramter = arguments.toString();
                }
            }
            logger.info(className + ":用户【" + usernameInfo + "】在ip为：【" + IpUtils.getIpAddr(request) + "】的机器上操作了【" + myLog.value() + "】|方法为:【" + methodName + "】| 参数为:【" + paramter + "】");
        }

    }

}
